<?php
declare (strict_types=1);

namespace app\admin\controller\tally;

use app\admin\controller\CommonController;
use app\common\model\AclUser;
use app\common\model\TallyCollect;
use app\common\model\TallyCollectRatio;
use app\common\model\TallyCustom;
use ffhome\frame\service\DictDataService;
use think\db\BaseQuery;
use think\facade\Db;

class Collect extends CommonController
{
    protected $modelName = TallyCollect::MODEL_NAME;
    protected $alias = 'coll';

    protected function buildWhere(array $param): array
    {
        if (!empty($param['coll_collect_month_ge'])) {
            $param['coll_collect_month_ge'] = $param['coll_collect_month_ge'] . '-01';
        }
        if (!empty($param['coll_collect_month_le'])) {
            $param['coll_collect_month_le'] = $param['coll_collect_month_le'] . '-01';
        }
        $where = parent::buildWhere($param);
        if (auth('roleAccounting')) {
            $where[] = ['c.accounting_id', '=', currentUserId()];
        }
        return $where;
    }

    protected function indexPage($param)
    {
        $param['m_collect_month_ge'] = date('Y-m');
        return parent::indexPage($param);
    }

    protected function setDefaultValueInAddPage(array $row): array
    {
        $row['custom_id'] = 0;
        return parent::setDefaultValueInAddPage($row);
    }

    protected function getBaseModel(): BaseQuery
    {
        return parent::getBaseModel()
            ->leftJoin(TallyCustom::MODEL_NAME . ' c', "c.id={$this->alias}.custom_id")
            ->leftJoin(AclUser::MODEL_NAME . ' a', "a.id=c.accounting_id")
            ->leftJoin('system_uploadfile up', "up.id={$this->alias}.path_id");
    }

    protected function getSearchFields(): string
    {
        return "{$this->alias}.*,DATE_FORMAT({$this->alias}.collect_month,'%Y-%m') _month"
            . ",concat(a.username,a.nickname) accounting_name,c.number,c.name custom_name"
            . ",up.url path_url,up.original_name path_name";
    }

    protected function getFilterFields(): array
    {
        return ['id', 'custom_id', 'collect_month', 'invoice_type', 'serve_type', 'article', 'money', 'remark',
            'invoice_status', 'invoice_date', 'path_id', 'status', 'collect_date', 'first_date', 'second_date'];
    }

    protected function editPage(array $row)
    {
        $ratioList = Db::name(TallyCollectRatio::MODEL_NAME)->alias('r')
            ->leftJoin(AclUser::MODEL_NAME . ' u', 'r.assigner_id=u.id')
            ->where('collect_id', $row['id'])->field('r.*,u.nickname assigner_name')
            ->order('id asc')->select()->toArray();
        $this->assign('ratioList', $ratioList);
        return parent::editPage($row);
    }

    protected function onBeforeAdd(array &$data)
    {
        $data['accounting_id'] = TallyCustom::getAccountingIdById($data['custom_id']);
        parent::onBeforeAdd($data);
    }

    protected function onBeforeSave(array &$data, array $row = [])
    {
        $data['collect_month'] = $data['collect_month'] . '-01';
        if (empty($data['invoice_date'])) unset($data['invoice_date']);
        if (empty($data['collect_date'])) unset($data['collect_date']);
        if (empty($data['first_date'])) unset($data['first_date']);
        if (empty($data['second_date'])) unset($data['second_date']);
        parent::onBeforeSave($data, $row);
    }

    protected function getExportHeader()
    {
        return [
            [lang('common.month'), '_month'],
            [lang('custom.number'), 'number'],
            [lang('custom.name'), 'custom_name'],
            [lang('accounting.name'), 'accounting_name'],
            [lang('collect.invoice_type'), 'invoice_type'],
            [lang('collect.serve_type'), 'serve_type'],
            [lang('collect.article'), 'article'],
            [lang('collect.money'), 'money'],
            [lang('collect.remark'), 'remark'],
            [lang('collect.invoice_status'), 'invoice_status'],
            [lang('collect.invoice_date'), 'invoice_date'],
            [lang('collect.status'), 'status'],
            [lang('collect.first_date'), 'first_date'],
            [lang('collect.second_date'), 'second_date'],
        ];
    }

    protected function convertExportData(&$list)
    {
        foreach ($list as &$vo) {
            $vo['invoice_type'] = DictDataService::getNameByValue($vo['invoice_type'], 'invoice_type_list');
            $vo['serve_type'] = DictDataService::getNameByValue($vo['serve_type'], 'serve_type_list');
            $vo['invoice_status'] = DictDataService::getNameByValue($vo['invoice_status'], 'collect_invoice_status_list');
            $vo['status'] = DictDataService::getNameByValue($vo['status'], 'collect_status_list');
        }
    }

    public function byAssigner()
    {
        $list = Db::name(TallyCollectRatio::MODEL_NAME)->alias('r')
            ->leftJoin(TallyCollect::MODEL_NAME . ' coll', 'r.collect_id=coll.id')
            ->leftJoin(AclUser::MODEL_NAME . ' u', 'r.assigner_id=u.id')
            ->field('u.id,concat(u.username,u.nickname) assigner_name,round(sum(coll.money*r.ratio/100),2) total_money')
            ->where($this->operateWhere())->group('u.id')->order('total_money desc')->select()->toArray();
        $this->assign('list', $list);
        return $this->fetch();
    }

    public function byCustom()
    {
        $subSql = Db::name(TallyCollect::MODEL_NAME)->alias('coll')
            ->leftJoin(TallyCustom::MODEL_NAME . ' c', "c.id=coll.custom_id")
            ->field('c.id,c.number,c.name,coll.collect_month,coll.money'
                . ',ifnull((select sum(cr.ratio) from e_tally_collect_ratio cr where cr.collect_id=coll.id),0) ratio')
            ->where($this->operateWhere())->buildSql(true);
        $sql = "select d.id,d.number,d.name custom_name,sum(d.money),round(sum(d.money*d.ratio/100),2) total_money"
            . " from {$subSql} d group by d.id order by total_money desc";
        $list = Db::query($sql);
        $this->assign('list', $list);
        return $this->fetch();
    }

    private function operateWhere(): array
    {
        $param = $this->request->param();
        if (!isset($param['coll_collect_month_ge'])) {
            $param['coll_collect_month_ge'] = date('Y-m');
        }
        $where = $this->buildWhere($param);
        if (empty($param['r_assigner_id_eq'])) {
            $param['r_assigner_id_eq'] = 0;
        }
        if (empty($param['coll_custom_id_eq'])) {
            $param['coll_custom_id_eq'] = 0;
        }
        $this->assign('param', $param);
        return $where;
    }
}
